// 知识点1：类的移动构造函数：参数为该类类型的右值引用，任何额外参数须有默认参数，一旦资源被移动，源对象对移动之后的资源已经不再有控制权，最后源对象会被销毁。注意，移动构造函数是“窃取”资源，并不会分配资源。

// 知识点2：移动操作不会报出任何异常，因为其不分配资源，所以我们需要告知标准库，以方便一起处理时多做一些额外的工作——加上noexpect(C++11新标准)，在类的声明和定义是都需要指出noexpect

// 知识点3：不抛出异常的移动构造函数和移动赋值运算符必须标记为noexpect——解释见书本P474页

// 知识点4：移动后的源对象可能会在移动后被销毁，所以必须进入可析构的状态——将源对象的指针成员置为nullptr来实现

// 知识点5：当一个类为其自身定义了拷贝构造函数和拷贝赋值运算符或者析构函数，且其所有数据成员皆可移动构造时，那么编译器将不会再为该类合成移动构造函数和移动赋值运算符

// 知识点6：移动右值、拷贝左值、没有移动构造函数时，右值也会被拷贝

// 知识点7：所有五个拷贝控制成员应该在类中一起出现！
// String &String::operator=(String &&rhs) NOEXCEPT {
//   if (this != &rhs) {
//     free();
//     elements = rhs.elements;
//     end = rhs.end;
//     rhs.elements = rhs.end = nullptr; //将源对象置为可析构的状态
//   }
//   return *this;
// }
// String::String(String &&s) NOEXCEPT : elements(s.elements), end(s.end) {
//   s.elements = s.end = nullptr; //将源对象置为可析构的状态
// }